'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.syncToServer = exports.cleanOtherVersion = exports.syncToLocalStorage = exports.syncToLocalStorageRaw = exports.EmptyResult = undefined;

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

var _safeStringify = require('../safeStringify');

var _xhr = require('../ajax/xhr');

var _safeJson = require('../safeJson');

var _safeJson2 = _interopRequireDefault(_safeJson);

var _simpleForEach = require('../simpleForEach');

var _simpleForEach2 = _interopRequireDefault(_simpleForEach);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var count = 0;
var genKey = function genKey(key) {
    var now = new Date().getTime();
    return key + '__' + now + '_' + count++;
};
var getSyncItem = function getSyncItem(key, data, first) {
    var regKey = new RegExp('^' + key + '__\\d+_\\d+(__full)?');
    var rst = [];
    var item = void 0;
    var resultItem = void 0;
    for (var k in data) {
        if (!regKey.test(k)) {
            continue;
        }
        item = (0, _safeJson2.default)(data[k]);
        resultItem = {
            key: k,
            val: item,
            raw: data[k]
        };
        if (first && first(item, k)) {
            return resultItem;
        }
        rst.push(resultItem);
    }
    return first ? null : rst;
};
var getFirstItem = function getFirstItem(key) {
    var first = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
        return true;
    };

    return getSyncItem(key, localStorage, first);
};
var replaceLocalStorageKey = function replaceLocalStorageKey(key, newKey) {
    localStorage.setItem(newKey, localStorage.getItem(key));
    localStorage.removeItem(key);
};
var regFull = /__full$/;
var EmptyResult = exports.EmptyResult = {};
var syncToLocalStorageRaw = exports.syncToLocalStorageRaw = function syncToLocalStorageRaw() {
    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
        key = _ref.key,
        getData = _ref.getData,
        done = _ref.done,
        _ref$interval = _ref.interval,
        interval = _ref$interval === undefined ? 5000 : _ref$interval,
        concatData = _ref.concatData,
        checkConcat = _ref.checkConcat,
        _ref$maxSize = _ref.maxSize,
        maxSize = _ref$maxSize === undefined ? 8000 : _ref$maxSize;

    var save = function save() {
        var data = getData();
        if (data === EmptyResult) {
            return;
        }
        var _key = void 0,
            item = void 0;
        if (checkConcat) {
            item = getFirstItem(key, function (item, key) {
                if (regFull.test(key)) {
                    return false;
                }
                if (!checkConcat(data, item)) {
                    return false;
                }
                var saveData = (0, _safeStringify.safeStringify)(data.data);
                var newLen = item.raw.length + saveData.length;
                console.log('合并后长度', newLen);
                if (newLen >= maxSize) {
                    replaceLocalStorageKey(key, key + '__full');
                    return false;
                }
                return true;
            });
        }
        if (!item) {
            _key = genKey(key);
        } else {
            _key = item.key;
            data = concatData(data, item.val);
        }

        localStorage.setItem(_key, (0, _safeStringify.safeStringify)(data));
        done && done();
    };

    var handler = setInterval(save, interval);
    var cancel = function cancel() {
        clearInterval(handler);
    };
    return {
        save: save,
        cancel: cancel
    };
};

var syncToLocalStorage = function syncToLocalStorage() {
    var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

    var _ref2$version = _ref2.version,
        version = _ref2$version === undefined ? '1.0.0' : _ref2$version,
        getData = _ref2.getData,
        checkConcat = _ref2.checkConcat,
        other = (0, _objectWithoutProperties3.default)(_ref2, ['version', 'getData', 'checkConcat']);

    var _getData = function _getData() {
        var data = getData();
        data.__version = version;
        return data;
    };
    var _checkConcat = function _checkConcat(data, oldData) {
        if (!oldData.__version !== data.__version) {
            return false;
        }
        return checkConcat(data, oldData);
    };
    return syncToLocalStorageRaw((0, _extends3.default)({}, other, {
        getData: _getData,
        checkConcat: _checkConcat
    }));
};

exports.syncToLocalStorage = syncToLocalStorage;
var cleanOtherVersion = exports.cleanOtherVersion = function cleanOtherVersion(key, version) {
    var items = getSyncItem(key, localStorage);
    (0, _simpleForEach2.default)(items, function () {
        var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
            _ref3$key = _ref3.key,
            key = _ref3$key === undefined ? '' : _ref3$key,
            val = _ref3.val;

        if (key && val.__version !== version) {
            localStorage.removeItem(key);
        }
    });
};

var toServer = function toServer(item) {
    var _item$val = item.val,
        _item$val$requestArgs = _item$val.requestArgs,
        requestArgs = _item$val$requestArgs === undefined ? {} : _item$val$requestArgs,
        data = _item$val.data;

    var itemKey = item.key;
    if (!requestArgs.url || !data) {
        localStorage.removeItem(itemKey);
        return;
    }
    return (0, _xhr.xhr)((0, _extends3.default)({}, requestArgs, {
        body: data
    })).then(function () {
        localStorage.removeItem(itemKey);
    });
};
var syncToServerRaw = function syncToServerRaw() {
    var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
        key = _ref4.key,
        done = _ref4.done,
        _ref4$interval = _ref4.interval,
        interval = _ref4$interval === undefined ? 10000 : _ref4$interval,
        _ref4$version = _ref4.version,
        version = _ref4$version === undefined ? '' : _ref4$version,
        _ref4$retryRemove = _ref4.retryRemove,
        retryRemove = _ref4$retryRemove === undefined ? 2 : _ref4$retryRemove;

    var errItems = {};
    var getItem = function getItem() {
        return getFirstItem(key, function (item) {
            if (version && item.__version !== version) {
                return false;
            }
            return true;
        });
    };
    var errHandler = function errHandler(itemKey) {
        if (itemKey in errItems) {
            errItems[itemKey]++;
            if (errItems[itemKey] > retryRemove) {
                localStorage.removeItem(itemKey);
                delete errItems[itemKey];
            }
            return;
        }
        errItems[itemKey] = 1;
    };

    var sync = function sync() {
        var item = getItem();
        var itemKey = item.key;
        return toServer(item).catch(function () {
            errHandler(itemKey);
        });
    };
    var handler = setInterval(sync, interval);
    var cancel = function cancel() {
        clearInterval(handler);
    };
    return {
        sync: sync,
        cancel: cancel
    };
};
var syncToServer = function syncToServer() {
    var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

    var _ref5$version = _ref5.version,
        version = _ref5$version === undefined ? '1.0.0' : _ref5$version,
        _ref5$cleanOldVersion = _ref5.cleanOldVersion,
        cleanOldVersion = _ref5$cleanOldVersion === undefined ? false : _ref5$cleanOldVersion,
        key = _ref5.key,
        other = (0, _objectWithoutProperties3.default)(_ref5, ['version', 'cleanOldVersion', 'key']);

    if (cleanOldVersion) {
        cleanOtherVersion(key, version);
    }
    return syncToServerRaw((0, _extends3.default)({
        key: key,
        version: version
    }, other));
};
exports.syncToServer = syncToServer;